package com.crissy.userService.service.impl;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.crissy.userService.common.CrissyFinal;
import com.crissy.userService.common.RedisFinal;
import com.crissy.userService.common.Result;
import com.crissy.userService.entity.User;
import com.crissy.userService.entity.UserInfo;
import com.crissy.userService.entity.dto.UserDTO;
import com.crissy.userService.mapper.UserInfoMapper;
import com.crissy.userService.mapper.UserMapper;
import com.crissy.userService.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Crissy-月下闲人
 * @since 2023-11-10
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private UserMapper userMapper;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 用户登录逻辑处理
     *
     * @param user 用户对象，包含登录所需信息（如用户名、密码等）
     * @return Result<UserInfo> 登录结果，成功时包含用户信息和token；失败时返回错误信息
     */
    @Override
    public Result<UserDTO> toLogin(User user) {
        // 根据用户提供的信息查询用户是否存在
        UserInfo userInfo = userMapper.loginSelect(user);
        if (userInfo == null) {
            // 用户不存在或密码错误，返回登录失败信息
            return Result.fail(401, "用户名或密码错误!");
        }

        // 生成随机的token
        String token = RandomUtil.randomString(CrissyFinal.TOKEN_LEN);

        // 将用户信息及token存入Redis缓存，以token为键，用户信息为值，设置过期时间
        stringRedisTemplate.opsForValue()
                .set(RedisFinal.REDIS_KEY_PREFIX_USER_TOKEN + token, JSONUtil.toJsonStr(userInfo), RedisFinal.TOKEN_EXPIRE_TTL, TimeUnit.SECONDS);

        // 返回登录成功的结果，包含用户信息和生成的token
        return Result.success(token, new UserDTO(userInfo));
    }


    @Override
    public Result<String> toLogout(String token) {
        // 删除Redis 缓存的用户token
        Boolean delete = stringRedisTemplate.delete(RedisFinal.REDIS_KEY_PREFIX_USER_TOKEN + token);
        // 如果删除失败，则返回失败结果
        if (BooleanUtil.isFalse(delete)) {
            return Result.fail(401, "退出失败!");
        }
        // 返回退出成功的结果
        return Result.success(200, "退出成功!");
    }


    @Override
    public Result<UserDTO> toRegister(User user) {
        // 判断用户名是否已存在
        if (userMapper.existUser(user.getUsername()))
            return Result.fail(401, "用户名已存在!");
        try {
            // 插入用户信息
            userMapper.insert(user);
            // 插入用户信息对应的信息
            userInfoMapper.insert(new UserInfo(user.getId()));
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail(401, "注册失败!");
        }
        // 登录成功，返回登录结果
        return toLogin(user);
    }

    /**
     * 根据token初始化用户信息。
     *
     * @param token 用户的token，用于认证和获取用户信息。
     * @return Result<UserDTO> 返回用户信息的结果对象。如果token无效，返回认证失败的信息；如果有效，返回用户信息。
     */
    @Override
    public Result<UserDTO> toInit(String token) {
        // 构造Redis中用户token的键名
        String key = RedisFinal.REDIS_KEY_PREFIX_USER_TOKEN + token;

        // 从Redis中获取存储的用户信息
        String userJson = stringRedisTemplate.opsForValue().get(key);
        if (StrUtil.isBlank(userJson)) {
            // 如果用户信息不存在于Redis中，则认证失败
            return Result.fail(401, "认证失败，请重新登录!");
        }
        // 将从Redis中获取的用户信息转换为UserDTO对象，并返回成功结果
        return Result.success(JSONUtil.toBean(userJson, UserDTO.class));
    }


    @Override
    public Result<UserDTO> toDelete(String token) {
        stringRedisTemplate.delete(RedisFinal.REDIS_KEY_PREFIX_USER_TOKEN + token);
        return null;
    }
}
